package com.yuyang.wifi.views.recyclerview.adapter;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import com.yuyang.wifi.views.recyclerview.model.LoadMoreItem;
import com.yuyang.wifi.views.recyclerview.model.RefreshHeaderItem;
import com.yuyang.wifi.views.recyclerview.swipe.OnLoadMoreListener;
import com.yuyang.wifi.views.recyclerview.swipe.OnRefreshListener;
import com.yuyang.wifi.views.recyclerview.swipe.RefreshStatus;
import com.yuyang.wifi.views.recyclerview.swipe.SwipeLoadMoreTrigger;
import com.yuyang.wifi.views.recyclerview.swipe.SwipeRefreshTrigger;
import com.yuyang.wifi.views.recyclerview.swipe.SwipeTrigger;

import java.util.List;

import androidx.recyclerview.widget.RecyclerView;

import static android.content.ContentValues.TAG;


/**
 * Created by tik on 17/8/11.
 * 带有下拉刷新功能的RecyclerViewAdapter
 */

public abstract class BaseRefreshRecyclerViewAdapter<DataType> extends RecyclerViewAdapterWrapper<DataType> {
    //Refresh
    private RefreshHeaderItem mRefreshHeaderItem;
    private LoadMoreItem mLoadMoreItem;

    private int mStatus = RefreshStatus.STATUS_DEFAULT;

    private int mRefreshLimitHeight = 160;
    private int mLoadMoreLimitHeight = 100;
    private boolean mAutoLoading;
    private int mRefreshCompleteDelayDuration = -999;
    private int mRefreshAnimationDuration = -999;
    private int mLoadMoreCompleteDelayDuration = -999;
    private int mLoadMoreAnimationDuration = -999;
    private int mAnimationDuration = 300;
    private OnRefreshListener mRefreshListener;
    private OnLoadMoreListener mLoadMoreListener;
    public static int mRefreshHeaderMaxHeight = 1600;
    public static int mLoadMoreMaxHeight = 1600;

    public int getAnimationDuration() {
        return mAnimationDuration;
    }

    public void setAnimationDuration(int animationDuration) {
        mAnimationDuration = animationDuration;
    }

    public int getLoadMoreCompleteDelayDuration() {
        if (mLoadMoreCompleteDelayDuration < -1) {
            return getLoadMoreAnimationDuration();
        }
        return mLoadMoreCompleteDelayDuration;
    }

    public void setLoadMoreCompleteDelayDuration(int loadMoreCompleteDelayDuration) {
        mLoadMoreCompleteDelayDuration = loadMoreCompleteDelayDuration;
    }

    public int getLoadMoreAnimationDuration() {
        if (mLoadMoreAnimationDuration < -1) {
            return getAnimationDuration();
        }
        return mLoadMoreAnimationDuration;
    }

    public void setLoadMoreAnimationDuration(int loadMoreAnimationDuration) {
        mLoadMoreAnimationDuration = loadMoreAnimationDuration;
    }

    public int getRefreshCompleteDelayDuration() {
        if (mRefreshCompleteDelayDuration < -1) {
            return getRefreshAnimationDuration();
        }
        return mRefreshCompleteDelayDuration;
    }

    public void setRefreshCompleteDelayDuration(int refreshCompleteDelayDuration) {
        mRefreshCompleteDelayDuration = refreshCompleteDelayDuration;
    }

    public int getRefreshAnimationDuration() {
        if (mRefreshAnimationDuration < -1) {
            return getAnimationDuration();
        }
        return mRefreshAnimationDuration;
    }

    public void setRefreshAnimationDuration(int refreshAnimationDuration) {
        mRefreshAnimationDuration = refreshAnimationDuration;
    }


    public ViewGroup getRefreshHeaderContainer() {
        return (ViewGroup) mRefreshHeaderItem.getView();
    }

    public ViewGroup getLoadMoreContainer() {
        return (ViewGroup) mLoadMoreItem.getView();
    }

    public OnLoadMoreListener getLoadMoreListener() {
        return mLoadMoreListener;
    }

    public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
        mLoadMoreListener = loadMoreListener;
    }

    public OnRefreshListener getRefreshListener() {
        return mRefreshListener;
    }

    public void setRefreshListener(OnRefreshListener refreshListener) {
        mRefreshListener = refreshListener;
    }


    public int getRefreshLimitHeight() {
        return mRefreshLimitHeight;
    }

    public void setRefreshLimitHeight(int refreshLimitHeight) {
        mRefreshLimitHeight = refreshLimitHeight;
        resetRefreshHeaderView();
    }

    public void setLoadMoreLimitHeight(int loadMoreLimitHeight) {
        mLoadMoreLimitHeight = loadMoreLimitHeight;
        resetLoadMoreView();
    }

    public int getLoadMoreLimitHeight() {
        return mLoadMoreLimitHeight;
    }

    public View.OnTouchListener getOnTouchListener() {
        return mOnTouchListener;
    }

    public void setOnTouchListener(View.OnTouchListener onTouchListener) {
        mOnTouchListener = onTouchListener;
    }

    public void setRefreshHeaderView(View view) {
        if (view instanceof SwipeRefreshTrigger) {
            LinearLayout linearLayout = createLinearLayout(view, mRefreshHeaderMaxHeight, Gravity.BOTTOM);
            mRefreshHeaderItem = new RefreshHeaderItem(linearLayout);
            mRefreshHeaderItem.init(view);
            mRecyclerView.setOnTouchListener(mOnTouchListener);
            resetRefreshHeaderView();
        } else {
            Log.e(TAG, "Refresh header view must be an implement of SwipeRefreshTrigger");
        }
    }


    @Override
    protected void afterRecyclerViewPrepared() {
        super.afterRecyclerViewPrepared();
        resetLoadMoreView();
    }

    protected void checkItemHeight() {
        if (getItemHeight() <= 0) {
//			throw new BaseRecyclerViewException("尚未在Adapter中设置ItemHeight");
            Log.e("RefreshRecyclerView", "尚未在Adapter中设置ItemHeight");
        }
    }

    public void setLoadMoreFooterView(View view) {
        if (view instanceof SwipeLoadMoreTrigger) {
            checkItemHeight();
            addRecyclerViewLayoutListener();
            LinearLayout linearLayout = createLinearLayout(view, mLoadMoreMaxHeight, Gravity.TOP);
            mLoadMoreItem = new LoadMoreItem(linearLayout);
            mLoadMoreItem.init(view);
            mRecyclerView.setOnTouchListener(mOnTouchListener);
        } else {
            Log.e(TAG, "Load more footer view must be an implement of SwipeLoadTrigger");
        }
    }

    public LinearLayout createLinearLayout(View view, int height, int gravity) {
        LinearLayout linearLayout = new LinearLayout(mContext);
        linearLayout.setGravity(gravity);
        RecyclerView.LayoutParams layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height);
        linearLayout.setLayoutParams(layoutParams);
        linearLayout.addView(view);
        return linearLayout;
    }

    public void resetLoadMoreView() {
        if (mLoadMoreItem == null || mLoadMoreItem.getView() == null || mLoadMoreLimitHeight < 0)
            return;
        View view = mLoadMoreItem.getView();
        RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
        layoutParams.bottomMargin = -mLoadMoreMaxHeight;
        view.setLayoutParams(layoutParams);
    }

    public void resetRefreshHeaderView() {
        if (mRefreshHeaderItem == null || mRefreshHeaderItem.getView() == null || mRefreshLimitHeight <= 0)
            return;
        View view = mRefreshHeaderItem.getView();
        RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
        layoutParams.topMargin = -mRefreshHeaderMaxHeight;
        view.setLayoutParams(layoutParams);
    }

    @Override
    public int getItemCount() {
        return mOriginalAdapter.getItemCount() + getOtherItemCount();
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (positionIsRefreshHeaderItem(position)) {
            mRefreshHeaderItem.onBindViewHolder((BaseViewHolder) holder, position);
            return;
        }
        if (positionIsHeaderItem(position)) {
            mHeaderItems.get(getHeaderItemIndex(position)).onBindViewHolder((BaseViewHolder) holder, position);
            return;
        }
        if (positionIsRemainAreaItem(position)) {
            mRemainAreaItem.onBindViewHolder((BaseViewHolder) holder, position);
            return;
        }
        if (positionIsFooterItem(position)) {
            mFooterItems.get(getFooterItemIndex(position)).onBindViewHolder((BaseViewHolder) holder, position);
            return;
        }
        if (positionIsLoadMoreItem(position)) {
            mLoadMoreItem.onBindViewHolder((BaseViewHolder) holder, position);
            return;
        }
        position = position - mHeaderItems.size();
        if (hasSetRefreshHeaderEnable()) position--;
        try {
            onBindViewHolder2(holder, position);
        } catch (Throwable e) {
            e.printStackTrace();
        }

    }

    @Override
    public int getItemViewType(int position) {
        if (positionIsRefreshHeaderItem(position)) {
            return mRefreshHeaderItem.getItemType();
        }
        if (positionIsHeaderItem(position)) {
            return mHeaderItems.get(getHeaderItemIndex(position)).getItemType();
        }

        if (positionIsRemainAreaItem(position)) {
            return mRemainAreaItem.getItemType();
        }

        if (positionIsFooterItem(position)) {
            return mFooterItems.get(getFooterItemIndex(position)).getItemType();
        }
        if (positionIsLoadMoreItem(position)) {
            return mLoadMoreItem.getItemType();
        }
        if (hasSetRefreshHeaderEnable()) position--;
        return getItemViewType2(position);
    }

    protected int getHeaderItemIndex(int position) {
        if (hasSetRefreshHeaderEnable()) return position - 1;
        return position;
    }

    protected int getFooterItemIndex(int position) {
        position = position - mHeaderItems.size() - mOriginalAdapter.getItemCount();
        if (hasSetRefreshHeaderEnable()) position--;
        if (hasFullDataArea()) {
            position--;
        }
        return position;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (typeIsRefreshHeaderItem(viewType)) {
            return new BaseViewHolder(mRefreshHeaderItem.getView());
        }
        if (typeIsLoadMoreItem(viewType)) {
            return new BaseViewHolder(mLoadMoreItem.getView());
        }
        return super.onCreateViewHolder(parent, viewType);
    }

    public BaseRefreshRecyclerViewAdapter(List objects, Context context) {
        super(context, objects);
    }

    @Override
    protected View createRemainAreaView(int height) {
        View remainAreaView = super.createRemainAreaView(height);
        if (remainAreaView == null) {
            remainAreaView = new View(mContext);
            RecyclerView.LayoutParams layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
            remainAreaView.setBackgroundColor(Color.RED);
            layoutParams.bottomMargin = height;
            remainAreaView.setLayoutParams(layoutParams);
        }
        return remainAreaView;
    }

    @Override
    public boolean wantFullDataArea() {
        return super.wantFullDataArea() || hasSetLoadMoreEnable();
    }

    public boolean positionIsLoadMoreItem(int position) {
        if (!hasSetLoadMoreEnable()) {
            return false;
        }
        int loadMoreItemPosition = mHeaderItems.size() + mOriginalAdapter.getItemCount();
        if (hasSetRefreshHeaderEnable()) {
            loadMoreItemPosition++;
        }
        if (hasFullDataArea()) {
            loadMoreItemPosition++;
        }
        return position == loadMoreItemPosition;
    }

    public boolean positionIsRefreshHeaderItem(int position) {
        if (!hasSetRefreshHeaderEnable()) {
            return false;
        }
        return position == 0;
    }

    public boolean positionIsRemainAreaItem(int position) {
        if (hasSetRefreshHeaderEnable()) position--;
        return hasFullDataArea() && position == mHeaderItems.size() + mOriginalAdapter.getItemCount();
    }

    public boolean positionIsHeaderItem(int position) {
        if (hasSetLoadMoreEnable()) return position > 0 && position < mHeaderItems.size();
        return position < mHeaderItems.size();
    }

    public boolean positionIsFooterItem(int position) {
        int count = mHeaderItems.size() + mOriginalAdapter.getItemCount();
        if (hasFullDataArea()) count++;
        if (hasSetRefreshHeaderEnable()) count++;
        return position >= count && position < count + mFooterItems.size();
    }


    public int getOtherItemCount() {
        int count = mHeaderItems.size() + mFooterItems.size();
        if (hasFullDataArea()) {
            count++;
        }
        if (hasSetLoadMoreEnable()) {
            count++;
        }
        if (hasSetRefreshHeaderEnable()) {
            count++;
        }
        return count;
    }

    public boolean typeIsLoadMoreItem(int type) {
        return mLoadMoreItem != null && mLoadMoreItem.getItemType() == type;
    }

    public boolean typeIsRefreshHeaderItem(int type) {
        return mRefreshHeaderItem != null && mRefreshHeaderItem.getItemType() == type;
    }

    public boolean hasSetRefreshHeaderEnable() {
        return mRefreshHeaderItem != null;
    }

    public boolean hasSetLoadMoreEnable() {
        return mLoadMoreItem != null;
    }

    public int getLoadMoreVisibleHeight() {
        RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) mLoadMoreItem.getView().getLayoutParams();
        return mLoadMoreMaxHeight + lp.bottomMargin;
    }

    public int getRefreshHeaderVisibleHeight() {
        RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) mRefreshHeaderItem.getView().getLayoutParams();
        return mRefreshHeaderMaxHeight + lp.topMargin;
    }

    public void setRefreshHeaderVisibleHeight(int height, boolean automatic) {
        if (height < 0) height = 0;
        View view = mRefreshHeaderItem.getView();
        RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams();
        lp.topMargin = height - mRefreshHeaderMaxHeight;
        view.setLayoutParams(lp);
        mRefreshCallback.onMove(height, isRefreshingState(), automatic);
    }

    public void setLoadMoreVisibleHeight(int moveY, boolean automatic) {
        if (moveY > 0) moveY = 0;
        View view = mLoadMoreItem.getView();
        RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams();
        lp.bottomMargin = -moveY - mLoadMoreMaxHeight;
        view.setLayoutParams(lp);
        mLoadMoreCallback.onMove(moveY, isLoadingMoreState(), automatic);
    }

    private boolean onCheckCanLoadMore() {
        if (mLoadMoreItem != null && mLoadMoreItem.getView() != null && mLoadMoreItem.getView().getParent() != null) {
            return true;
        }
        int position = mRecyclerView.getLinearLayoutManager().findLastCompletelyVisibleItemPosition();
        int count = getItemCount();
        return position == count - 2;
    }

    private boolean onCheckCanRefresh() {
        if (mRefreshHeaderItem != null && mRefreshHeaderItem.getView() != null && mRefreshHeaderItem.getView().getParent() != null) {
            return true;
        } else {
            return false;
        }
    }

    private View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {
        int currentY;
        int lastY;
        int moveY;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if (RefreshStatus.isRefreshing(mStatus) || isLoadingMoreState()) {
                        return true;
                    }
                    lastY = (int) event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (isRefreshingState() || isLoadingMoreState()) {
                        return true;
                    }
                    currentY = (int) event.getY();
                    moveY = currentY - lastY;
                    if (RefreshStatus.isStatusDefault(mStatus)) {
                        if (moveY > 0 && onCheckCanRefresh()) {
                            mRefreshCallback.onPrepare();
                            setStatus(RefreshStatus.STATUS_SWIPING_TO_REFRESH);
                        } else if (moveY < 0 && onCheckCanLoadMore()) {
                            mLoadMoreCallback.onPrepare();
                            setStatus(RefreshStatus.STATUS_SWIPING_TO_LOAD_MORE);
                        }
                    } else if (RefreshStatus.isRefreshStatus(mStatus)) {
                        if (moveY <= 0) {
                            setStatus(RefreshStatus.STATUS_DEFAULT);
                            return false;
                        }
                    } else if (RefreshStatus.isLoadMoreStatus(mStatus)) {
                        if (moveY >= 0) {
                            setStatus(RefreshStatus.STATUS_DEFAULT);
                            return false;
                        }
                    }

                    if (RefreshStatus.isRefreshStatus(mStatus)) {
                        if (RefreshStatus.isSwipingToRefresh(mStatus) || RefreshStatus.isReleaseToRefresh(mStatus)) {
                            if (moveY > mRefreshLimitHeight) {
                                setStatus(RefreshStatus.STATUS_RELEASE_TO_REFRESH);
                            } else {
                                setStatus(RefreshStatus.STATUS_SWIPING_TO_REFRESH);
                            }
                            setRefreshHeaderVisibleHeight(moveY, false);
                        }
                    } else if (RefreshStatus.isLoadMoreStatus(mStatus)) {
                        if (RefreshStatus.isSwipingToLoadMore(mStatus) || RefreshStatus.isReleaseToLoadMore(mStatus)) {
                            if (-moveY >= mLoadMoreLimitHeight) {
                                setStatus(RefreshStatus.STATUS_RELEASE_TO_LOAD_MORE);
                            } else {
                                setStatus(RefreshStatus.STATUS_SWIPING_TO_LOAD_MORE);
                            }
                            setLoadMoreVisibleHeight(moveY, false);
                        }
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                    if (isRefreshingState() || isLoadingMoreState()) {
                        return true;
                    }
                    if (RefreshStatus.isSwipingToRefresh(mStatus)) {
                        scrollSwipingToRefreshToDefault();
                        return true;
                    } else if (RefreshStatus.isReleaseToRefresh(mStatus)) {
                        setRefreshingState();
                        scrollReleaseToRefreshToRefreshing();
                        return true;
                    } else if (RefreshStatus.isSwipingToLoadMore(mStatus)) {
                        scrollSwipingToLoadMoreToDefault();
                        return true;
                    } else if (RefreshStatus.isReleaseToLoadMore(mStatus)) {
                        setLoadingMoreState();
                        scrollReleaseToLoadMoreToLoadingMore();
                        return true;
                    }
                    break;
            }
            return false;
        }
    };

    private boolean isRefreshingState() {
        return RefreshStatus.isRefreshing(mStatus);
    }

    private boolean isLoadingMoreState() {
        return RefreshStatus.isLoadingMore(mStatus);
    }

    private void setLoadingMoreState() {
        mStatus = RefreshStatus.STATUS_LOADING_MORE;
    }

    private void setRefreshingState() {
        mStatus = RefreshStatus.STATUS_REFRESHING;
    }

    private void setStatus(int status) {
        mStatus = status;
    }

    public void setLoadingMore(boolean loadingMore) {
        if (!hasSetLoadMoreEnable()) {
            return;
        }
        this.mAutoLoading = loadingMore;
        if (loadingMore) {
            if (RefreshStatus.isStatusDefault(mStatus) && onCheckCanLoadMore()) {
                setStatus(RefreshStatus.STATUS_SWIPING_TO_LOAD_MORE);
                scrollDefaultToLoadingMore();
            }
        } else {
            if (isLoadingMoreState()) {
                mLoadMoreCallback.onComplete();
                mRecyclerView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        scrollLoadingMoreToDefault();
                    }
                }, getLoadMoreCompleteDelayDuration());
            }
        }
    }

    public void setRefreshing(boolean refreshing) {
        if (!hasSetRefreshHeaderEnable()) {
            return;
        }
        this.mAutoLoading = refreshing;
        if (refreshing) {
            if (RefreshStatus.isStatusDefault(mStatus) && onCheckCanRefresh()) {
                setStatus(RefreshStatus.STATUS_SWIPING_TO_REFRESH);
                scrollDefaultToRefreshing();
            }
        } else {
            if (isRefreshingState()) {
                mRefreshCallback.onComplete();
                mRecyclerView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        scrollRefreshingToDefault();
                    }
                }, getRefreshCompleteDelayDuration());
            }
        }
    }


    private void smoothScrollLoadMoreTo(int height, Animator.AnimatorListener listener) {
        ValueAnimator animator = ValueAnimator.ofInt(getLoadMoreVisibleHeight(), height);
        animator.setDuration(getLoadMoreAnimationDuration());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int height = (int) animation.getAnimatedValue();
                setLoadMoreVisibleHeight(-height, true);
            }
        });
        animator.addListener(listener);
        animator.start();
    }

    private void smoothScrollRefreshHeaderTo(int height, Animator.AnimatorListener listener) {
        ValueAnimator animator = ValueAnimator.ofInt(getRefreshHeaderVisibleHeight(), height);
        animator.setDuration(getRefreshAnimationDuration());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int height = (int) animation.getAnimatedValue();
                setRefreshHeaderVisibleHeight(height, true);
            }
        });
        animator.addListener(listener);
        animator.start();
    }

    private void scrollDefaultToLoadingMore() {
        ValueAnimator animator = ValueAnimator.ofInt(getLoadMoreVisibleHeight(), mLoadMoreLimitHeight);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            int childCount = getItemCount() - 1;

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int height = (int) animation.getAnimatedValue();
                setLoadMoreVisibleHeight(-height, true);
                mRecyclerView.moveToPosition(childCount);
            }
        });
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                setLoadingMoreState();
                mLoadMoreCallback.onLoadMore();
                if (mLoadMoreListener != null) {
                    mLoadMoreListener.onLoadMore();
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                resetLoadMoreState();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animator.start();
    }

    private void scrollDefaultToRefreshing() {

        ValueAnimator animator = ValueAnimator.ofInt(getRefreshHeaderVisibleHeight(), mRefreshLimitHeight);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int height = (int) animation.getAnimatedValue();
                setRefreshHeaderVisibleHeight(height, true);
                mRecyclerView.moveToPosition(0);
            }
        });
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                setRefreshingState();
                mRefreshCallback.onRefresh();
                if (mRefreshListener != null) {
                    mRefreshListener.onRefresh();
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                resetRefreshStatus();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animator.start();
    }

    private void scrollSwipingToLoadMoreToDefault() {
        smoothScrollLoadMoreTo(0, new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                resetLoadMoreState();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                resetLoadMoreState();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }

    private void scrollSwipingToRefreshToDefault() {
        scrollRefreshingToDefault();
    }


    private void scrollLoadingMoreToDefault() {
        smoothScrollLoadMoreTo(0, new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                resetLoadMoreState();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                resetLoadMoreState();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }


    private void scrollRefreshingToDefault() {
        smoothScrollRefreshHeaderTo(0, new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                resetRefreshStatus();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                resetRefreshStatus();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
    }

    private void scrollReleaseToLoadMoreToLoadingMore() {
        smoothScrollLoadMoreTo(mLoadMoreLimitHeight, new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mLoadMoreCallback.onLoadMore();
                if (mLoadMoreListener != null) {
                    mLoadMoreListener.onLoadMore();
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                resetLoadMoreState();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }

    private void scrollReleaseToRefreshToRefreshing() {
        smoothScrollRefreshHeaderTo(mRefreshLimitHeight, new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mRefreshCallback.onRefresh();
                if (mRefreshListener != null) {
                    mRefreshListener.onRefresh();
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                resetRefreshStatus();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }

    public void resetRefreshStatus() {
        mStatus = RefreshStatus.STATUS_DEFAULT;
        mRefreshCallback.onReset();
        resetRefreshHeaderView();
    }

    public void resetLoadMoreState() {
        mStatus = RefreshStatus.STATUS_DEFAULT;
        mLoadMoreCallback.onReset();
        resetLoadMoreView();
    }


    /**
     * refresh event callback
     */
    abstract class RefreshCallback implements SwipeTrigger, SwipeRefreshTrigger {
    }

    /**
     * load more event callback
     */
    abstract class LoadMoreCallback implements SwipeTrigger, SwipeLoadMoreTrigger {
    }


    RefreshCallback mRefreshCallback = new RefreshCallback() {
        @Override
        public void onRefresh() {
            SwipeRefreshTrigger trigger = mRefreshHeaderItem.getSwipeRefreshTrigger();
            if (trigger != null) {
                trigger.onRefresh();
            }
        }

        @Override
        public void onPrepare() {
            SwipeTrigger trigger = mRefreshHeaderItem.getSwipeTrigger();
            if (trigger != null) {
                trigger.onPrepare();
            }
        }

        @Override
        public void onMove(int y, boolean isComplete, boolean automatic) {
            SwipeTrigger trigger = mRefreshHeaderItem.getSwipeTrigger();
            if (trigger != null) {
                trigger.onMove(y, isComplete, automatic);
            }
        }

        @Override
        public void onRelease() {
            SwipeTrigger trigger = mRefreshHeaderItem.getSwipeTrigger();
            if (trigger != null) {
                trigger.onRelease();
            }
        }

        @Override
        public void onComplete() {
            SwipeTrigger trigger = mRefreshHeaderItem.getSwipeTrigger();
            if (trigger != null) {
                trigger.onComplete();
            }
        }

        @Override
        public void onReset() {
            SwipeTrigger trigger = mRefreshHeaderItem.getSwipeTrigger();
            if (trigger != null) {
                trigger.onReset();
            }
        }
    };

    LoadMoreCallback mLoadMoreCallback = new LoadMoreCallback() {

        @Override
        public void onLoadMore() {
            SwipeLoadMoreTrigger trigger = mLoadMoreItem.getLoadMoreTrigger();
            if (trigger != null) {
                trigger.onLoadMore();
            }
        }

        @Override
        public void onPrepare() {
            SwipeTrigger trigger = mLoadMoreItem.getSwipeTrigger();
            if (trigger != null) {
                trigger.onReset();
            }
        }

        @Override
        public void onMove(int y, boolean isComplete, boolean automatic) {
            SwipeTrigger trigger = mLoadMoreItem.getSwipeTrigger();
            if (trigger != null) {
                trigger.onMove(y, isComplete, automatic);
            }
        }

        @Override
        public void onRelease() {
            SwipeTrigger trigger = mLoadMoreItem.getSwipeTrigger();
            if (trigger != null) {
                trigger.onRelease();
            }
        }

        @Override
        public void onComplete() {
            SwipeTrigger trigger = mLoadMoreItem.getSwipeTrigger();
            if (trigger != null) {
                trigger.onComplete();
            }
        }

        @Override
        public void onReset() {
            SwipeTrigger trigger = mLoadMoreItem.getSwipeTrigger();
            if (trigger != null) {
                trigger.onReset();
            }
        }
    };


}
